﻿using System;
using System.Collections.Generic;
using System.Linq;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Architecture;
using Autodesk.Revit.Exceptions;
using YJKSparseDistance.Properties;
using YJKGeometryFuncs;
using YJKInspectModelFunc;
using YJKInspectModelFunc.ModelLayer;

namespace YJKSparseDistance.ModelLayer
{
	internal class BoundaryCurveArrayBean : BaseCurveBean
	{
		internal List<BoundaryCurveBean> LstBoundaryCurveBean
		{
			get
			{
				return this.m_lstBoundaryCurveBean;
			}
		}

		internal List<DoorCurveBean> LstDoorCurveBean
		{
			get
			{
				return this.m_lstDoorCurveBean;
			}
		}

		public List<WallLocationCurveBean> LstAllWallLocationCurves
		{
			get
			{
				return this.m_LstAllWallLocationCurves;
			}
		}

		public BoundaryCurveArrayBean(List<BaseBoundarySegmentPacker> inputValue)
		{
			this.m_lstPacker = inputValue;
			this.SetSubBeans();
			this.SetBeanCut(this.LstBoundaryCurveBean);
			this.SetBeanCut(this.m_lstFreeEndBoundaryCurveBean);
			new List<Curve>();
			foreach (BoundaryCurveBean boundaryCurveBean in this.m_lstBoundaryCurveBean)
			{
				this.m_lstCurvePacker.AddRange(boundaryCurveBean.LstCurvePacker);
			}
			List<XYZ> freeEnd = this.GetFreeEnd();
			this.m_lstAllFreeEnd.AddRange(freeEnd);
			for (int i = 0; i < this.m_lstDoorCurveBean.Count; i++)
			{
				for (int j = 0; j < this.m_lstDoorCurveBean.Count; j++)
				{
					if (i < j)
					{
						this.m_lstDoorCurveBean[i].CutThisDoor(this.m_lstDoorCurveBean[j]);
					}
				}
			}
		}

		private List<XYZ> GetFreeEnd()
		{
			XYZCompare compare = XYZCompare.GetCompare();
			Dictionary<XYZ, int> dictionary = new Dictionary<XYZ, int>(compare);
			compare.Reset();
			foreach (BoundaryCurveBean boundaryCurveBean in this.m_lstFreeEndBoundaryCurveBean)
			{
				foreach (Curve curve in boundaryCurveBean.NowOffestCurve())
				{
					if (!(null == curve))
					{
						for (int i = 0; i < 2; i++)
						{
							if (dictionary.ContainsKey(curve.GetEndPoint(i)))
							{
								Dictionary<XYZ, int> dictionary2 = dictionary;
								XYZ endPoint = curve.GetEndPoint(i);
								int num = dictionary2[endPoint];
								dictionary2[endPoint] = num + 1;
							}
							else
							{
								dictionary.Add(curve.GetEndPoint(i), 1);
							}
						}
					}
				}
			}
			compare.Reset();
			return (from n in dictionary
			where n.Value == 1
			select n.Key).ToList<XYZ>();
		}

		private void SetSubBeans()
		{
			List<List<Curve>> list = null;
			Room tempRoom = null;
			WallLocationCurveBean wallLocationCurveBean = null;
			foreach (BaseBoundarySegmentPacker baseBoundarySegmentPacker in this.m_lstPacker)
			{
				if (baseBoundarySegmentPacker.ThisRoomPacker != null)
				{
					tempRoom = baseBoundarySegmentPacker.ThisRoomPacker.ThisRoom;
				}
				this.AddWallLocationCurve(tempRoom, ref wallLocationCurveBean, baseBoundarySegmentPacker);
				Curve curve;
				list = Utility.DoBoundarySgementSplite(baseBoundarySegmentPacker, out curve, true);
				if (null != curve)
				{
					this.m_lstFreeEndBoundaryCurveBean.Add(new BoundaryCurveBean(curve, baseBoundarySegmentPacker, true));
					foreach (BaseDoorPacker baseDoorPacker in baseBoundarySegmentPacker.LstDoors)
					{
						int num = -1;
						double num2 = double.MaxValue;
						for (int i = 0; i < list[0].Count; i++)
						{
							double num3 = Utility.DistanceNonZValue(list[0][i], baseDoorPacker);
							if (num2 > num3)
							{
								num2 = num3;
								num = i;
							}
						}
						Curve curve2 = null;
						if (num != -1)
						{
							curve2 = this.CalculateOffestDoorCurve(list, num, curve2, tempRoom);
							this.LstDoorCurveBean.Add(new DoorCurveBean(list[0][num], baseDoorPacker, curve2));
							list[0].RemoveAt(num);
						}
					}
					foreach (Curve inputCurve in list[1])
					{
						this.LstBoundaryCurveBean.Add(new BoundaryCurveBean(inputCurve, baseBoundarySegmentPacker, false));
					}
				}
			}
		}

		private Curve CalculateOffestDoorCurve(List<List<Curve>> tempBoundaryCurves, int nearDoorIndex, Curve tempOffestCurve, Room tempRoom)
		{
			if (tempRoom != null)
			{
				tempOffestCurve = Utility.GetAOffestCurveInRoom(tempBoundaryCurves[0][nearDoorIndex], tempRoom, double.Parse(Resources.Str_OffestValue));
			}
			return tempOffestCurve;
		}

		private void AddWallLocationCurve(Room tempRoom, ref WallLocationCurveBean tempWallCurveBean, BaseBoundarySegmentPacker tempBoundarySegmentPacker)
		{
			int wallId = -1;
			int linkInstanceId = -1;
			if (tempRoom == null || tempRoom.Level == null || tempRoom.Location == null)
			{
				return;
			}
			double elevation = tempRoom.Level.Elevation;
			if (tempBoundarySegmentPacker.ThisElement != null && tempBoundarySegmentPacker.ThisElement is Wall)
			{
				Wall wall = tempBoundarySegmentPacker.ThisElement as Wall;
				Curve curve = (wall.Location as LocationCurve).Curve;
				if (tempBoundarySegmentPacker.UseRevitLinkInstance != null)
				{
					curve = curve.CreateTransformed(tempBoundarySegmentPacker.UseTransform);
				}
				if (!Geometry.IsEqual(curve.GetEndPoint(0).Z, elevation) || !Geometry.IsEqual(curve.GetEndPoint(1).Z, elevation))
				{
                    curve = YJKInspectModelFunc.Utility.TransformCurveAtZAixs(curve, elevation, true);
				}
				wallId = wall.Id.IntegerValue;
				linkInstanceId = tempBoundarySegmentPacker.LinkInstanceId;
				tempWallCurveBean = new WallLocationCurveBean(wallId, linkInstanceId, curve);
				if (!this.m_LstAllWallLocationCurves.Contains(tempWallCurveBean))
				{
					this.m_LstAllWallLocationCurves.Add(tempWallCurveBean);
					return;
				}
				tempWallCurveBean = this.m_LstAllWallLocationCurves.Find((WallLocationCurveBean k) => k.WallId == wallId && k.LinkInstanceId == linkInstanceId);
			}
		}

		private void SetBeanCut(List<BoundaryCurveBean> inputValue)
		{
			for (int i = 0; i < inputValue.Count; i++)
			{
				for (int j = 0; j < inputValue.Count; j++)
				{
					if (i != j)
					{
						BoundaryCurveBean boundaryCurveBean = inputValue[i];
						BoundaryCurveBean boundaryCurveBean2 = inputValue[j];
						if (!(null == boundaryCurveBean.NowCanUseCurve()) && !(null == boundaryCurveBean2.NowCanUseCurve()))
						{
							IntersectionResultArray tempIntersectionResult;
							SetComparisonResult setComparisonResult;
							try
							{
								setComparisonResult = boundaryCurveBean.NowCanUseCurve().Intersect(boundaryCurveBean2.NowCanUseCurve(), out tempIntersectionResult);
							}
							catch (Autodesk.Revit.Exceptions.InvalidOperationException)
							{
                                setComparisonResult = (SetComparisonResult)3;
								tempIntersectionResult = null;
							}
							if (setComparisonResult == SetComparisonResult.Overlap)
							{
								this.SetCutedOffestValue(tempIntersectionResult, boundaryCurveBean, boundaryCurveBean2);
								this.SetCutedOffestValue(tempIntersectionResult, boundaryCurveBean2, boundaryCurveBean);
							}
						}
					}
				}
			}
		}

		private void SetCutedOffestValue(IntersectionResultArray tempIntersectionResult, BoundaryCurveBean tempBeanOne)
		{
			if (null != tempBeanOne.NowCanUseCurve())
			{
				tempBeanOne.SetCutedCurves(Utility.CutCurvePreserve(tempBeanOne.NowCanUseCurve(), tempBeanOne.NowCanUseCurve().Project(tempIntersectionResult.get_Item(0).XYZPoint).Parameter));
			}
		}

		private void SetCutedOffestValue(IntersectionResultArray tempIntersectionResult, BoundaryCurveBean tempBeanOne, BoundaryCurveBean tempBeanTwo)
		{
			if (null != tempBeanOne.NowCanUseCurve())
			{
				tempBeanOne.SetCutedCurves(Utility.CutCurvePreserve(tempBeanOne.NowCanUseCurve(), tempBeanOne.NowCanUseCurve().Project(tempIntersectionResult.get_Item(0).XYZPoint).Parameter, tempBeanTwo.ThisBaseCurve));
			}
		}

		private List<BoundaryCurveBean> m_lstBoundaryCurveBean = new List<BoundaryCurveBean>();

		private List<BoundaryCurveBean> m_lstFreeEndBoundaryCurveBean = new List<BoundaryCurveBean>();

		private List<DoorCurveBean> m_lstDoorCurveBean = new List<DoorCurveBean>();

		private List<BaseBoundarySegmentPacker> m_lstPacker;

		private List<WallLocationCurveBean> m_LstAllWallLocationCurves = new List<WallLocationCurveBean>();
	}
}
